using System;
using System.Threading;
using Core;
using Microsoft.SPOT;
using SolarDevices.Configuration;

namespace SolarDevices
{
    public class SolarSystem : IDisposable
    {
        private const int POLL_PERIOD = 600000; // log data to SD card every 10 minutes
        private IRegisterTable _controller;
        private IRegisterTable _inverter;
        private readonly SolarConfiguration _config;
        private Timer _timer;
        private bool _summaryCreated;

        #region Constructors

        public SolarSystem()
        {
            _config = new SolarConfiguration();
            if (_config.ChargeController == ChargeControllerType.Classic)
            {
                _controller = new ClassicRegisterTable();
            }
            else if (_config.ChargeController == ChargeControllerType.Outback)
            {
                _controller = new OutbackRegisterTable();
            }
            else if (_config.ChargeController == ChargeControllerType.TriStarTCP)
            {
                _controller = new TriStarRegisterTable(ModbusTCPDevice.GetSingleton());
            }
            else if (_config.ChargeController == ChargeControllerType.TriStarRTU)
            {
                _controller = new TriStarRegisterTable(ModbusRTUDevice.GetSingleton());
            }
            if (_config.Inverter == InverterType.Outback)
            {
                _inverter = new OutbackRegisterTable();
            }
        }

        public void Dispose()
        {
            StopPolling();
            if (_controller != null)
            {
                _controller.Dispose();
                _controller = null;
            }
            if (_inverter != null)
            {
                _inverter.Dispose();
                _inverter = null;
            }
        }

        #endregion

        public void StartPolling()
        {
            if (_timer == null)
                SetupTimer();
            if (_controller != null)
                _controller.StartPolling();
            if (_inverter != null)
                _inverter.StartPolling();
        }

        private void StopPolling()
        {
            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }

        }

        private void SetupTimer()
        {
            _timer = new Timer(PollDevice, null, POLL_PERIOD, POLL_PERIOD);
        }

        private void PollDevice(object state)
        {
            try
            {
                var ce = new ChargeEvent();
                _controller.ReadChargeEvent(ref ce);
                if (_inverter != null)
                {
                    _inverter.ReadInverterEvent(ref ce);
                }
                var logger = EventLogger.GetLogger();
                logger.LogDayEvent(ce);
                var hour = DateTime.Now.Hour;
                if (hour == 20 && _summaryCreated == false)
                {
                    _summaryCreated = true;
                    logger.CreateSummary(ce);
                }
                else if (hour < 20)
                {
                    _summaryCreated = false;
                }
            }
            catch (Exception ex)
            {
                DebugLogger.TryLog(ex);
            }

        }

        public ChargeState ReadChargeState()
        {
            try
            {
                ChargeState chargeState = _controller.ReadChargeState();
                if (_inverter != null)
                {
                    _inverter.AddInverterData(ref chargeState);
                }
                return chargeState;
            }
            catch (Exception ex)
            {
                DebugLogger.TryLog(ex);
                throw ex;
            }
        }

    }
}
